package sketch.generator.examples;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import sketch.generator.ChainValueGenerator;
import sketch.generator.CompositeGenerator;
import sketch.generator.IGenerator;
import sketch.generator.IIterationLink;
import sketch.generator.LinkCreator;
import sketch.generator.SequentialLink;
import sketch.util.Checker;

public class ExhaustiveSequatialValueGenerator<T> extends CompositeGenerator<SequentialValue<T>> {

	private List<IGenerator<?>> generators
	    = new ArrayList<IGenerator<?>>();
	
	public ExhaustiveSequatialValueGenerator(Collection<T> values) {
		Checker.checkNull(values, "The values for adding could not be null!");
		int length = values.size();
		for(int size = 1; size <= length; size++) {
			//add generator for generating permutation
			PermutationSequentialValueGenerator permSeqGenerator
			    = new PermutationSequentialValueGenerator();
			for(int i = 0; i < size; i++) {
				IGenerator<?> chainGenerator = new ChainValueGenerator(values);
				permSeqGenerator.add(chainGenerator);
			}
			this.generators.add(permSeqGenerator);
		}
	}
	
	public ExhaustiveSequatialValueGenerator(T... values) {
		Checker.checkNull(values, "input values for constructor could not be null!");
		int length = values.length;
		for(int size = 1; size <= length; size++) {
			//add generator for generating permutation
			PermutationSequentialValueGenerator permSeqGenerator
			    = new PermutationSequentialValueGenerator();
			for(int i = 0; i < size; i++) {
				IGenerator chainGenerator = new ChainValueGenerator(values);
				permSeqGenerator.add(chainGenerator);
			}
			this.generators.add(permSeqGenerator);
		}
	}
	
	@Override
	public void reset() {
		super.reset();
		for(IGenerator<?> generator : generators) {
			generator.reset();
		}
	}
	
	@Override
	public SequentialValue<T> generateCurrent() {
		SequentialLink iterator = (SequentialLink) this.iterator;
		return (SequentialValue<T>) iterator.current();
	}

	@Override
	public IIterationLink getInitializedIterator() {
		return LinkCreator.createSequentialLink(this.generators);
	}

}
